package org.je.image;

import java.awt.image.BufferedImage;

import org.je.util.DynBuffer;
import org.je.util.NumberUtil;

/**
 * @author fanyifeng 2012-11-7 下午6:08:35
 */
public class ImageStream
{
	/**
	 * @param img
	 * @return data
	 */
	public static byte[] toBytes(BufferedImage img) {
		int w = img.getWidth();
		int h = img.getHeight();
		DynBuffer bf = new DynBuffer();

		bf.append(NumberUtil.int2bytes(w));
		bf.append(NumberUtil.int2bytes(h));
		for (int y = 0; y < h; ++y) {
			for (int x = 0; x < w; ++x) {
				int argb = img.getRGB(x ,y);
				if (argb == 0) {
					bf.append(zero);
				} else {
					bf.append(argb2bytes(argb));
				}
			}
		}
		return bf.toArray();
	}

	/**
	 * @param data
	 * @param tpy
	 * @return bufferedimage
	 */
	public static BufferedImage toImage(byte[] data, int tpy) {
		int w = NumberUtil.bytes2int(data);
		int h = NumberUtil.bytes2int(data ,4);
		BufferedImage img = ImageUtil.createCompatibleImage(w ,h ,tpy);
		fillRGBs(img ,w ,h ,data);
		return img;
	}

	/**
	 * @param data
	 * @param tpy
	 * @return bufferedimage
	 */
	public static BufferedImage toBufferedImage(byte[] data, int type) {
		int w = NumberUtil.bytes2int(data);
		int h = NumberUtil.bytes2int(data ,4);
		BufferedImage img = new BufferedImage(w,h,type);
		fillRGBs(img ,w ,h ,data);
		return img;
	}

	private static void fillRGBs(BufferedImage img, int w, int h, byte[] data) {
		int off = 8;
		for (int y = 0; y < h; ++y) {
			for (int x = 0; x < w; ++x) {
				int argb = getArgb(data ,off);
				if (argb == 0) {
					++off;
				} else {
					off += 4;
				}
				img.setRGB(x ,y ,argb);
			}
		}
	}

	private static byte[] argb2bytes(int argb) {
		byte[] arr = new byte[4];
		arr[0] = (byte) ( (argb & 0xff000000) >>> 24);
		arr[1] = (byte) ( (argb & 0xff0000) >> 16);
		arr[2] = (byte) ( (argb & 0x00ff00) >> 8);
		arr[3] = (byte) (argb & 0xff);
		return arr;
	}

	private static int getArgb(byte[] b, int off) {
		if (b[off] == 0)
			return 0;
		int n = (b[off] & 0xff) << 24;
		n |= ( (b[off + 1] & 0xff) << 16);
		n |= ( (b[off + 2] & 0xff) << 8);
		n |= (b[off + 3] & 0xff);
		return n;
	}

	private static final byte[]	zero	= new byte[] { 0 };
}
